#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/7/15 14:54
# @File    : app.py
# @Description : -i http://pypi.tuna.tsinghua.edu.cn/simple/ --trusted-host pypi.tuna.tsinghua.edu.cn

import sys
from PySide6.QtCore import Qt
from PySide6.QtGui import QPen
from PySide6.QtWidgets import QApplication, QWidget
# -*- QtCharts 绘图相关类 -*-
from PySide6.QtCharts import QChart, QChartView, QAbstractBarSeries, QLineSeries, QBarSeries, QPieSeries, QBarSet, QBarCategoryAxis, QValueAxis

import numpy as np

class myChart(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('二维图表')
        self.showLine()
        self.showBar()
        #self.showPie()

    def showLine(self):
        """
        绘制螺旋曲线图
        """
        #（1）创建图表和视图
        chart = QChart()  # 创建一个图表对象
        chart.setTitle('螺旋曲线')  # 设置图表标题
        chartView = QChartView(self)  # 创建一个图表视图对象，需要传入self才能在界面上显示图表
        chartView.setGeometry(10, 10, 800, 600)  # 设置图表视图的几何大小
        chartView.setChart(chart)  # 设置图表视图所展示的图表

        #（2）创建序列并添加数据
        n = 1000
        pointList = np.linspace(1, 10 * 2 * np.pi, n)  # 创建一个包含1000个元素的有序数列

        lSeries1 = QLineSeries()  # 创建一个线性系列对象
        lSeries1.setName('Archimedes')  # 设置线性系列的名称
        for t in pointList:
            x = (1 + 0.618 * t) * np.cos(t)  # 计算螺旋曲线的x坐标
            y = (1 + 0.618 * t) * np.sin(t)  # 计算螺旋曲线的y坐标
            lSeries1.append(x, y)  # 将计算得到的坐标点添加到线性系列中
        chart.addSeries(lSeries1)  # 将线性系列添加到图表中

        lSeries2 = QLineSeries()  # 创建一个线性系列对象
        lSeries2.setName('hyperbolic')  # 设置线性系列的名称
        for t in pointList:
            x = 10 * 2 * np.pi * (np.cos(t) / t)  # 计算超球面曲线的x坐标
            y = 10 * 2 * np.pi * (np.sin(t) / t)  # 计算超球面曲线的y坐标
            lSeries2.append(x, y)  # 将计算得到的坐标点添加到线性系列中
        chart.addSeries(lSeries2)  # 将线性系列添加到图表中

        #（3）建立坐标轴
        chart.createDefaultAxes()  # 创建默认的坐标轴

    def showBar(self):
        """
        绘制柱状图
        """
        #（1）创建图表和视图
        chart = QChart()  # 创建一个图表对象
        chart.setTitle('2017～2021年高考人数和录取率')  # 设置图表标题
        chart.legend().setAlignment(Qt.AlignmentFlag.AlignTop)  # 设置图例的对齐方式
        chartView = QChartView(self)  # 创建一个图表视图对象，需要传入self才能在界面上显示图表
        chartView.setGeometry(10, 10, 800, 600)  # 设置图表视图的几何大小
        chartView.setChart(chart)  # 设置图表视图所展示的图表

        #（2）创建序列并添加数据
        number_signup = [940, 975, 1031, 1071, 1078]  # 高考报名人数
        signupSet = QBarSet('报考')  # 创建一个柱状系列集合对象，用于表示报考人数
        for i in range(0, 5):
            signupSet << number_signup[i]  # 将报考人数添加到集合中
        number_enroll = [700, 791, 820, 967.5, 689]  # 高考录取人数
        enrollSet = QBarSet('录取')  # 创建一个柱状系列集合对象，用于表示录取人数
        for i in range(0, 5):
            enrollSet << number_enroll[i]  # 将录取人数添加到集合中

        bSeries = QBarSeries()  # 创建一个柱状系列对象
        bSeries.append(signupSet)  # 将报考人数集合添加到柱状系列中
        bSeries.append(enrollSet)  # 将录取人数集合添加到柱状系列中
        bSeries.setLabelsVisible(True)  # 设置柱状图的标签可见
        bSeries.setLabelsPosition(QAbstractBarSeries.LabelsPosition.LabelsInsideEnd)  # 设置柱状图的标签位置
        chart.addSeries(bSeries)  # 将柱状系列添加到图表中

        lSeries = QLineSeries()
        lSeries.setName('趋势')  # 设置线性系列的名称，用于表示录取人数的趋势线
        for i in range(0, 5):
            lSeries.append(i, number_enroll[i]) # 将录取人数作为点坐标添加到线性系列中，x轴为年份索引，y轴为录取人数
        pen = QPen(Qt.GlobalColor.red)  # 创建一个红色画笔对象，用于绘制线条
        pen.setWidth(2)  # 设置线条宽度为2像素
        lSeries.setPen(pen)  # 设置线性系列的画笔属性
        lSeries.setPointLabelsVisible(True)  # 设置线性图上的点标签可见
        lSeries.setPointLabelsFormat('@yPoint 万')  # 设置点标签格式，显示y值（录取人数）并以“万”为单位

        chart.addSeries(lSeries)  # 将表示录取人数趋势的线性系列添加到图表中

        # （3）建立和设置坐标轴
        year = ['2017', '2018', '2019', '2020', '2021']  # 年份标签列表
        axisX = QBarCategoryAxis()  # 创建一个分类坐标轴对象，用于显示柱状图的横坐标轴标签
        axisX.setTitleText('年份')  # 设置分类坐标轴标题
        axisX.append(year)  # 将年份标签列表添加到分类坐标轴中
        chart.addAxis(axisX, Qt.AlignmentFlag.AlignBottom)  # 将分类坐标轴添加到图表底部，并与柱状图关联

        axisY = QValueAxis()  # 创建一个数值坐标轴对象，用于显示柱状图和趋势线的纵坐标轴
        axisY.setTitleText('人数（万）')  # 设置数值坐标轴标题
        chart.addAxis(axisY, Qt.AlignmentFlag.AlignLeft)  # 将数值坐标轴添加到图表左侧，并与柱状图和线性图关联

        bSeries.attachAxis(axisX)  # 将柱状系列与分类坐标轴关联
        bSeries.attachAxis(axisY)  # 将柱状系列与数值坐标轴关联
        lSeries.attachAxis(axisX)  # 将线性系列与分类坐标轴关联
        lSeries.attachAxis(axisY)  # 将线性系列与数值坐标轴关联

    def showPie(self):
        """
        绘制饼状图
        """
        # （1）创建图表和视图
        chart = QChart()  # 创建一个图表对象
        chart.setTitle('中国高等教育普及率')  # 设置图表标题
        chart.legend().setAlignment(Qt.AlignmentFlag.AlignLeft)  # 设置图例对齐方式为左对齐
        chartView = QChartView(self)  # 创建一个图表视图对象，需要传入self才能在界面上显示图表
        chartView.setGeometry(10, 10, 800, 600)  # 设置图表视图的几何大小
        chartView.setChart(chart)  # 设置图表视图所展示的图表

        # （2）创建序列并添加数据
        pieSet = {'儿童和老人': 35, '劳动人口': 49, '参加高考者': 7, '大学生': 8}  # 高等教育普及率数据字典

        pSeries = QPieSeries()  # 创建一个饼状图系列对象
        for item in pieSet.items():
            label = item[0] + '（%d%%）' % item[1]  # 格式化饼状图标签，包含百分比
            pSeries.append(label, item[1])  # 将标签和对应的数值（普及率）添加到饼状图系列中
        pSeries.setLabelsVisible(True)  # 设置饼状图的标签可见
        pSeries.setHoleSize(0.2)  # 设置饼状图中心空洞的大小，取值范围0-1之间
        pSeries.setPieSize(0.6)  # 设置饼状图的直径大小，取值范围0-1之间

        slice = pSeries.slices()[3]  # 获取特定切片（此处为第四个切片，索引从0开始）
        slice.setExploded(True)  # 将选中的切片分离出来，以便突出显示
        slice.setPen(QPen(Qt.GlobalColor.red))  # 设置切片的轮廓线颜色为红色
        slice.setBrush(Qt.GlobalColor.red)  # 设置切片的填充色为红色

        chart.addSeries(pSeries)  # 将饼状图系列添加到图表中
if __name__ == '__main__':# 初始化应用程序并创建主窗口实例
    app = QApplication(sys.argv)
    # 创建myChart类的实例，并显示在屏幕上
    w = myChart()
    w.show()
    # 运行事件循环，等待用户操作，直至退出应用
    sys.exit(app.exec())